PostgreSQL HOT与索引扫描
1 安装pageinspece 插件
2 Heap Only Tuple Scans(仅堆元组扫描)
2.1 HOT的特点与好处
•被更新的行存储在与旧行同一数据块中。
•可以有效的使用索引和表的块。
•可以降低VACUUM的必要性。
2.2 Update a Row Without HOT
- 没有HOT 特性时,隐藏旧行,插入新行,并且索引需要添加对应元组指向新的块。即便不是更新索引列,也会更新索引
2.3 How HOT Performs(Update a row with HOT)
使用HOT 特性时,索引不会进行维护,Tuple1 的ctid 指向Tpule2 ,这样索引就不需要维护。降低开销。
但是有一个问题, 取数据的时候需要扫描两行,增大开销。
2.4 How HOT Performs(Pruning of the line pointers)(修剪行指针)
2.5 How HOT Performs(Defragmentation of the dead tuples)空间整理
2.5.1 索引未修剪
- 索引访问索引元组。
- 获取ctid,指向(5,1)。
item1
指向Tuple1
。Tuple1
重新指向Tuple2
。- 完成回表动作。
2.5.2 索引修剪后
- 索引访问索引元组,取出ctid。
item1
指向item2
。item2
指向Tuple2
。- 完成回表动作。
2.6 HOT 执行过程
- 更新(5,1) 为(5,2) 能够指向
Tuple2
,t_informaask2 为HEAP_HOT_UPDATED
。 - 插入新行(5,2),t_informaask2 为
HEAP_HOT_UPDATED
。
2.7 HOT 不可用的情况(有问题)
1. 索引块占满情况。
2. 更新了主键列(更新主键列也会进行HOT)。
实验未成功,
3 仅索引扫描(Index-Only Scans)
- 取值都由索引提供,从这方面来讲是不需要回表的,但是由于仅索引扫描需要判断元组可见性,可见性由 tmin,tmax决定,而 索引不包含这些信息,所以 必须进行回表。造成性能降低。
- 为了提高性能,所以pg 引入了Visibility map 去判断是否元组是否可见。
3.1 判断流程
- Visibility Map 0th = 1 所有元组都可见,不需要回表扫描。
- Visibility Map 0th = 0 部分元组不可见,需要回表扫描。
4 实验
4.1 环境准备
create table t01(id int);
create index t01_idx_id ON t01 (id);
insert into t01 values(1);
postgres=# SELECT lp as tuple, t_xmin, t_xmax, t_field3 as t_cid, t_ctid
FROM heap_page_items(get_raw_page('t01', 0));
tuple | t_xmin | t_xmax | t_cid | t_ctid
-------+--------+--------+-------+--------
1 | 869 | 0 | 0 | (0,1)
(1 row)
4.2 UPDATE
postgres=# update t01 set id=2 where id=1;
UPDATE 1
postgres=# SELECT lp as tuple, t_xmin, t_xmax, t_field3 as t_cid, t_ctid
FROM heap_page_items(get_raw_page('t01', 0));
tuple | t_xmin | t_xmax | t_cid | t_ctid
-------+--------+--------+-------+--------
1 | 869 | 871 | 0 | (0,2)
2 | 871 | 0 | 0 | (0,2)
4.3 VCACCUM
postgres=# vacuum t01;
4.4 查看索引,索引元组仍然保留.
select * from bt_page_items('t01_idx_id',1);